﻿using AgileDevTool.Helpers;
using AgileDevTool.UserControls;
using AgileDevTool.Windows;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using webserver.core;

namespace AgileDevTool
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private static bool EmulatorDisplay = true;

        private static bool ExplorerDisplay = true;

        private static bool EditorDisplay = true;

        private static bool DebugDisplay = true;

        private static Brush PreBackground = null;

        private void DisplayUC_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var br = (Border)sender;
            var uc = br.Tag as string;
            switch (uc)
            {
                case "1":
                    {
                        if (EmulatorDisplay)
                        {
                            EmulatorDisplay=false;
                            uc_Emulator.Visibility= Visibility.Collapsed;
                            col_Emulator.Width=new GridLength(0);

                            PreBackground = br.Background;
                            br.Background=new SolidColorBrush(Color.FromArgb(255, 192, 192, 192));
                        }
                        else
                        {
                            EmulatorDisplay=true;
                            uc_Emulator.Visibility= Visibility.Visible;
                            col_Emulator.Width=new GridLength(300);
                            br.Background=PreBackground;
                        }
                        break;
                    }
                case "2":
                    {
                        if (ExplorerDisplay)
                        {
                            ExplorerDisplay=false;
                            uc_Explorer.Visibility= Visibility.Collapsed;
                            col_Explorer.Width=new GridLength(0);

                            PreBackground = br.Background;
                            br.Background=new SolidColorBrush(Color.FromArgb(255, 192, 192, 192));
                        }
                        else
                        {
                            ExplorerDisplay=true;
                            uc_Explorer.Visibility= Visibility.Visible;
                            col_Explorer.Width=new GridLength(200);
                            br.Background=PreBackground;
                        }
                        break;
                    }
                case "3":
                    {
                        if (EditorDisplay)
                        {
                            EditorDisplay=false;
                            uc_Editor.Visibility= Visibility.Collapsed;

                            PreBackground = br.Background;
                            br.Background=new SolidColorBrush(Color.FromArgb(255, 192, 192, 192));
                        }
                        else
                        {
                            EditorDisplay=true;
                            uc_Editor.Visibility= Visibility.Visible;
                            br.Background=PreBackground;
                        }
                        break;
                    }
                case "4":
                    {
                        if (DebugDisplay)
                        {
                            DebugDisplay=false;
                            uc_Debug.Visibility= Visibility.Collapsed;
                            row_Console.Height=new GridLength(0);

                            PreBackground = br.Background;
                            br.Background=new SolidColorBrush(Color.FromArgb(255, 192, 192, 192));
                        }
                        else
                        {
                            DebugDisplay=true;
                            uc_Debug.Visibility= Visibility.Visible;
                            row_Console.Height=new GridLength(300);
                            br.Background=PreBackground;
                        }
                        break;
                    }
            }
        }

        public static int _port = new Random().Next(5050, 9999);

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var project = CacheHelper.Projects.Where(w => w.LastOpenedAt.HasValue).OrderByDescending(o => o.LastOpenedAt.GetValueOrDefault()).FirstOrDefault();
            if (project == null)
            {
                var wd = new ChooseProjectWindow();
                wd.ProjectChoosed+=Wd_ProjectChoosed;
                wd.ShowDialog();
                return;
            }

            InitProject(project);

            if (CacheHelper.CurrentProject == null)
            {
                UIHelper.Toast(sp_Projects, "请先选择项目");
                return;
            }

            Build();

            StartService();

            Run();
        }

        private void InitProject(ProjectItem project)
        {
            if (!Directory.Exists(project.Path))
            {
                UIHelper.Toast(sp_Projects, "目录不存在："+project.Path);
                return;
            }

            var folderName = SecurityHelper.GetMD5String(project.Path);
            var folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dist", folderName);
            project.Dist = folder;

            CacheHelper.CurrentProject = project;
            Title = $"{project.Name}[{project.Path}]";

            var item = new FileItem
            {
                DisplayName=CacheHelper.CurrentProject.Name,
                Name=CacheHelper.CurrentProject.Path,
                Children = new List<FileItem>()
            };
            BuildExplorer(item, CacheHelper.CurrentProject.Path, "\\.git", "\\.vs");

            var items = new List<FileItem>();
            items.Add(item);
            UIHelper.tree1.ItemsSource = items;
        }

        private void BuildExplorer(FileItem item, string path, params string[] excepts)
        {
            var directories = Directory.GetDirectories(path);
            foreach (var directory in directories)
            {
                if (excepts!=null && excepts.Length>0)
                {
                    if (excepts.Any(a => $"{path}{a}".ToLower() == directory.ToLower()))
                    {
                        continue;
                    }
                }

                var name = Path.GetFileName(directory);
                var child = new FileItem
                {
                    DisplayName= name,
                    Name=directory,
                    Children=new List<FileItem>()
                };
                item.Children.Add(child);

                BuildExplorer(child, directory);
            }

            var files = Directory.GetFiles(path);
            foreach (var file in files)
            {
                if (excepts!=null && excepts.Length>0)
                {
                    if (excepts.Any(a => $"{path}{a}".ToLower() == file.ToLower()))
                    {
                        continue;
                    }
                }

                var name = Path.GetFileName(file);
                var child = new FileItem
                {
                    DisplayName= name,
                    Name=file,
                    Children=new List<FileItem>()
                };
                item.Children.Add(child);
            }
        }

        private void Save()
        {
            var file = UIHelper.tbk_File.Tag as string;
            if (!string.IsNullOrEmpty(file))
            {
                var content = UIHelper.rtb1.Text;
                File.WriteAllText(file, content, Encoding.UTF8);
            }
        }

        private void Build()
        {
            if (CacheHelper.CurrentProject == null)
            {
                UIHelper.Toast(sp_Projects, "请先选择项目");
                return;
            }

            FileHelper.CopyFolder(CacheHelper.CurrentProject.Path, CacheHelper.CurrentProject.Dist, true, "\\.git", "\\.vs");

            var source = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Projects", "index.html");
            var target = Path.Combine(CacheHelper.CurrentProject.Dist, "index.html");
            File.Copy(source, target);

            source = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Projects", "index.css");
            target = Path.Combine(CacheHelper.CurrentProject.Dist, "index.css");
            File.Copy(source, target);

            source = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Projects", "index.js");
            target = Path.Combine(CacheHelper.CurrentProject.Dist, "index.js");
            File.Copy(source, target);

            source = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Projects", "404.html");
            target = Path.Combine(CacheHelper.CurrentProject.Dist, "404.html");
            File.Copy(source, target);

            source = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Projects", "favicon.ico");
            target = Path.Combine(CacheHelper.CurrentProject.Dist, "favicon.ico");
            File.Copy(source, target);

            var pages = Directory.GetFiles(CacheHelper.CurrentProject.Dist, "*.ui", SearchOption.AllDirectories);
            foreach (var page in pages)
            {
                var html = page.Replace(".ui", ".html");
                var bytes = File.ReadAllBytes(page);
                File.WriteAllBytes(html, bytes);
            }
        }

        private void StartService()
        {
            TaskHelper.RunUseThread(() =>
            {
                var option = new StartOption
                {
                    Assembly = CacheHelper.CurrentProject.Dist,
                    BufferSize = 1024 * 1024,
                    Error404Page = "/404.html",
                    IndexPage = "/index.html",
                    Port = _port,
                    Routes = new List<RouteItem>(),
                    StaticFileExtensions = new Dictionary<string, string>()
                };

                InitStaticFileExtensions(option);

                var server = new Server(option);
                server.Runing += Server_Runing;
                server.ReceivedRequest += Server_ReceivedRequest;
                server.BeforeResponse += Server_BeforeResponse;
                server.Error += Server_Error;
                server.Start();
            });
        }

        private void Run()
        {
            if (CacheHelper.CurrentProject == null)
            {
                UIHelper.Toast(sp_Projects, "请先选择项目");
                return;
            }

            var url = $"http://127.0.0.1:{_port}";
            UIHelper.tbk_Url.Text = url;
            UIHelper.wb1.Navigate(url);
            ProcessRun(url);
        }

        public static void ProcessRun(string url)
        {
            var p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = false;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            p.Start();

            p.StandardInput.WriteLine($"start {url}&exit");
            p.StandardInput.AutoFlush = true;
            p.WaitForExit();
            p.Close();
        }

        private void Wd_ProjectChoosed(string path)
        {
            var project = CacheHelper.Projects.Where(w => w.Path == path).FirstOrDefault();
            if (project == null)
            {
                return;
            }

            InitProject(project);
        }

        private void ChooseProject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var wd = new ChooseProjectWindow();
            wd.ProjectChoosed+=Wd_ProjectChoosed;
            wd.ShowDialog();
        }

        private void Save_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Save();
        }

        private void Run_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (CacheHelper.CurrentProject == null)
            {
                UIHelper.Toast(sp_Projects, "请先选择项目");
                return;
            }

            Save();
            Build();
            //Run();
        }

        private void InitStaticFileExtensions(StartOption option)
        {
            option.StaticFileExtensions.Add(".txt", "text/plain");
            option.StaticFileExtensions.Add(".html", "text/html");
            option.StaticFileExtensions.Add(".css", "text/css");
            option.StaticFileExtensions.Add(".js", "application/x-javascript");
            option.StaticFileExtensions.Add(".json", "application/json");
            option.StaticFileExtensions.Add(".ico", "image/x-icon");
            option.StaticFileExtensions.Add(".jpeg", "image/jpeg");
            option.StaticFileExtensions.Add(".jpg", "image/jpeg");
            option.StaticFileExtensions.Add(".png", "image/png");
            option.StaticFileExtensions.Add(".gif", "image/gif");
            option.StaticFileExtensions.Add(".woff", "font/woff");
            option.StaticFileExtensions.Add(".woff2", "font/woff2");
            option.StaticFileExtensions.Add(".ttf", "font/ttf");
        }

        private void Server_Error(Exception ex)
        {
            LogHelper.WriteErrorAsync(ex.ToString());
        }

        private void Server_BeforeResponse(string responseContent)
        {
            if (responseContent.Length<100)
            {
                LogHelper.WriteAsync(responseContent);
            }
        }

        private void Server_ReceivedRequest(string requestContent, string ip)
        {
            LogHelper.WriteAsync($"{ip}\r\n{requestContent}");
        }

        private void Server_Runing(string address)
        {
            LogHelper.WriteAsync($"服务已启动：{address}");
        }
    }
}
